package com.king.designpatterns.行为模式.备忘录模式;

/**
 * 备忘录模式（Memento Pattern）又称为快照（Snapshot）模式或Token模式。
 *
 * 定义：在不破坏封装性的前提下，捕获一个对象的内部状态，并在该对象之外保存这个状态。这样，以后就可以将该对象恢复到原先保存的状态。
 *
 * 角色：
 *      ■ 发起人（Originator）角色：
 *          该角色记录当前时刻的内部状态，负责定义哪些属于备份范围的状态，负责创建和恢复备忘数据。
 *      ■ 备忘录（Memento）角色：
 *          该角色负责存储发起人角色的内部状态，在需要时提供发起人需要的内部状态数据。
 *      ■ 负责人（Caretaker）角色：
 *          该角色对备忘录角色进行管理、保存和提供备忘录。
 *
 * 场景：
 *      ■ 需要保存和恢复数据的相关状态场景。
 *      ■ 提供一个可回滚的操作。
 *      ■ 需要监控副本的场景。例如，监控一个对象的属性，但是监控又不应该作为系统的主业务来调用，它只是边缘应用，
 *          即使出现监控不准、错误报警也影响不大，因此一般做法是备份一个主线程中的对象，然后由分析程序来分析。
 *      ■ 数据库连接的事务管理使用的就是备忘录模式。
 *
 * 注意事项：
 *      ■ 备忘录的生命周期。
 *          备忘录创建出来就要在最近的代码中使用，要主动管理它的生命周期，建立就要使用，不使用就要立刻删除其引用，等待垃圾回收器对它的回收处理。
 *      ■ 备忘录的性能。
 *          不要在频繁建立备份的场景中使用备忘录模式，例如，for循环中，一是控制不了备忘录建立的对象数量；
 *          二是大对象的建立是要消耗资源的，需要考虑系统的性能。因此，如果出现这样的代码，设计师应该修改架构。
 *
 * @author king
 * @date 2021-06-11 10:15
 */
public class MementoPattern {
    public static void main(String[] args) {
        VersionControlSystem vcs = new VersionControlSystem();
        Document document = new Document();
        document.content = "content1";
        document.otherContent = "otherContent1";
        System.out.println(document);
        // 保存备份1
        vcs.add(document.save());
        document.content = "content2";
        document.otherContent = "otherContent2";
        System.out.println(document);
        // 保存备份2
        vcs.add(document.save());
        document.content = "content3";
        document.otherContent = "otherContent3";
        System.out.println(document);
        // 恢复版本1
        document.resume(vcs.get(1));
        System.out.println(document);
        // 恢复最新版本
        document.resume(vcs.getLastVersion());
        System.out.println(document);
    }
}
